package com.toutiao.score

import scala.math.{sqrt,min,max}

object SimpleFactory {
  
  def norm(vs:Map[String,Double]) = {
	if (vs.size > 0){
	    var s = vs.map(x => x._2*x._2).reduce(_+_)
	    s = sqrt(s)
	    vs.map(x => {
	      (x._1,x._2/s)
	    })
	 }
	 else {
	    vs
	 }
  }
	
  
  def cos(m1:Map[String,Double], s1:Double, m2:Map[String,Double], s2:Double):Double = {
    var s = 0.0
    for ( (k,v) <- m1){
      s += v*m2.getOrElse(k,0.0)
    }
    s/(s1*s2)
  }
  
  def cos(m1:Map[String,Double],s1:Double,m2:Map[String,Double],s2:Double,nn:Int):Double = {
    var s = 0.0
    var cnt = 0
    for ( (k,v) <- m1) {
      val vv = m2.getOrElse(k,0.0)
      s += v*vv
      if (vv > 0)
        cnt += 1
    }
    
    if (cnt > nn)
      s/(s1*s2)
    else
      0.0
  }
  
  
  def merge(m1:Map[String,Double],n1:Int,m2:Map[String,Double],n2:Int) = {
    val n = n1+n2
    var z = m1
    for ( (k,v) <- m2){
      var x = v*n2+z.getOrElse(k,0.0)*n1
      z += k->x/n
    }
    var s = z.map(x => x._2*x._2).reduce(_+_)
    s = sqrt(s)
    z.map( x => {
      (x._1,x._2/s)
    })
  }
  
  
  //val K1 = 20
  //val K2 = 20
  
  def merge(m1:Map[String,Double],n1:Int,m2:Map[String,Double],n2:Int,ss:Double) = {
    val n = n1+n2
    var z = 
      if (n1 > n2) m1
      else m2
    val m =
      if (n1 > n2) m2
      else m1
    val nn1 = 
      if (n1 > n2) n1
      else n2
    val nn2 =
      if (n1 > n2) n2
      else n1
    
    for ( (k,v) <- m) {
      var x = v*nn2*ss+z.getOrElse(k,0.0)*nn1
      z += k->x/n
    }
    var s = z.map(x => x._2*x._2).reduce(_+_)
    s = sqrt(s)
    z.map(x => {
      (x._1,x._2/s)
    })
  }

  val maxU = 0.85

  def cut(vs:Map[String,Double],size:Int=60) = {
    if (vs.size <= size){
      vs
    }
    else {
      val us = vs.toArray.sortBy(-_._2)
      val ss = us(size)._2
      val ns = vs.filter(_._2 > ss)
      val s = ns.map(x => x._2*x._2).reduce(_+_)
      ns.map(x => {(x._1,min(x._2/s,maxU))})
    }
  }  
  
}
